/*
 * ============================================================================
 *
 *       Filename:  easyapi.c
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  2014年04月18日 13时38分58秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  jianxi sun (jianxi), ycsunjane@gmail.com
 *   Organization:  
 *
 * ============================================================================
 */
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>

#include <curl/curl.h>

#include <lua.h>  
#include <lualib.h>  
#include <lauxlib.h> 


char user_pass[] = "freewifibox-report:FF3EF1FBFA2920168EDEF65410D1DA9B@";
char tag[1024] =  "&tag=1";

char *server_report;

char *json_send = NULL;
char *lastctltime = NULL;
char *reportlink = NULL;
char *ctrllink = NULL;
char *auth_key = NULL;

char *retbuf = NULL;

size_t ret_call( char *ptr, size_t size, size_t  nmemb,  void *userdata)
{
	int strsize = strlen(ptr) + 1;
	retbuf = realloc(retbuf, strsize);
	if(retbuf == NULL) {
		fprintf(stderr, "realloc failed\n");
		exit(-1);
	}
	strcat(retbuf, ptr);
	return size*nmemb;
}

static void *l_alloc (void *ud, void *ptr, size_t osize,
	size_t nsize) {
	(void)ud;  (void)osize;  /*  not used */
	if (nsize == 0) {
		free(ptr);
		return NULL;
	}
	else
		return realloc(ptr, nsize);
}

#define LUA_SCRIPT 	"echo.lua"

static char *get_luatable(lua_State *L, const char* table, const char* item)
{
	lua_getglobal(L, table);
	lua_pushstring(L, item);
	lua_gettable(L, -2);

	const char *buf;
	char *dest;
	buf = lua_tostring(L, -1);
	if(buf == NULL) {
		fprintf(stderr, "get table:%s, item:%s failed", table, item);
		return NULL;
	}

	int totalsize = strlen(buf) + 1;
	dest = malloc(totalsize);
	if(dest == 0) {
		fprintf(stderr, "get lua variable failed\n");
		exit(-1);
	}
	strncpy(dest, buf, totalsize);
	dest[totalsize] = 0;

	lua_pop(L, 2);
	return dest;
}


static char * get_luastr(lua_State *luaenv, char *variable)
{
	const char *buf;
	char *dest;
	int totalsize;

	lua_getglobal(luaenv, variable);
	buf = lua_tostring(luaenv, -1);
	if(buf == NULL) {
		fprintf(stderr, "variable：%s inexistence\n", variable);
		return NULL;
	}
	totalsize = strlen(buf) + 1;
	dest = malloc(totalsize);
	if(dest == 0) {
		fprintf(stderr, "get lua variable failed\n");
		exit(-1);
	}

	strncpy(dest, buf, totalsize);
	dest[totalsize] = 0;
	lua_pop(luaenv, 1);
	return dest;
}

lua_State *acl_lua_init()
{
	lua_State * luaenv = lua_newstate(l_alloc, NULL);
	if(luaenv == NULL) {
		printf("create lua_newstate failed\n");
		exit(-1);
	}
}

int get_json_send(lua_State *luaenv)
{
	char *buf;

	lua_pcall(luaenv, 0, 0, 0);

	if(lastctltime !=  NULL) free(lastctltime);
	lastctltime = get_luastr(luaenv, "LAST_CTRL_TIME");

	if(json_send != NULL) free(json_send); 
	json_send = get_luastr(luaenv, "JSON_SEND");
	if(json_send == NULL) exit(-1);

	if(reportlink != NULL) free(reportlink);
	reportlink = get_luastr(luaenv, "serverReport");
	if(reportlink == NULL) exit(-1);

	if(ctrllink != NULL) free(ctrllink);
	ctrllink = get_luastr(luaenv, "serverCtrl");
	if(ctrllink == NULL) exit(-1);

	if(auth_key == NULL) free(auth_key);
	auth_key = get_luatable(luaenv, "Data", "auth_key");
	if(auth_key == NULL) exit(-1);
}

static char *build_url(char *link, int num, ...)
{
	int totalsize = strlen(link) + strlen(user_pass) + 1;

	char *arg;
	va_list ap;
	va_start(ap, num);
	int i;
	for(i = 0; i < num; i++) {
		arg  =  va_arg(ap, char *);
		assert(arg != NULL);
		totalsize += strlen(arg);
	}
	va_end(ap);

	char *url = malloc(totalsize);
	if(url == NULL) {
		fprintf(stderr, "Malloc failed\n");
		exit(-1);
	}
	char *realurl = strstr(link, "//") + 2;
	int protosize = realurl - link;

	strncpy(url, link, protosize);
	url[protosize] = 0;
	strcat(url, user_pass);
	strcat(url, realurl);

	va_list ap2;
	va_start(ap2, num);
	for(i = 0; i < num; i++) {
		arg  =  va_arg(ap2, char *);
		strcat(url, arg);
	}
	va_end(ap2);

	return url;
}

int curl_send(char *url, char *data, void *callback)
{
	CURL *handle;
	handle = curl_easy_init();
	if(handle == NULL) {
		fprintf(stderr, "Init curl failed\n");
		exit(-1);
	}

	CURLcode ret;
#ifdef DEBUG
	/* set verbose */
	ret = curl_easy_setopt(handle, CURLOPT_VERBOSE, 1);
	if(ret != CURLE_OK) {
		fprintf(stderr, "set verbose option failed\n");
		exit(-1);
	}
#endif

	/* set post */
	ret = curl_easy_setopt(handle, CURLOPT_POST, 1);
	if(ret != CURLE_OK) {
		fprintf(stderr, "set post option failed\n");
		exit(-1);
	}

	if(data != NULL) {
		/* set post data */
		ret = curl_easy_setopt(handle, CURLOPT_POSTFIELDS, data);
		if(ret != CURLE_OK) {
			fprintf(stderr, "set post data option failed\n");
			exit(-1);
		}
	}

	if(callback != NULL) {
		/* set ret_call */
		ret = curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, callback);
		if(ret != CURLE_OK) {
			fprintf(stderr, "set post data option failed\n");
			exit(-1);
		}
	}

	ret = curl_easy_setopt(handle, CURLOPT_URL, url);
	if(ret != CURLE_OK) {
		fprintf(stderr, "set url option failed\n");
		exit(-1);
	}

	ret = curl_easy_perform(handle);
	if(ret != CURLE_OK) {
		fprintf(stderr, "perform curl option failed\n");
		exit(-1);
	}

	curl_easy_cleanup(handle);
	return 0;
}

int main()
{
	lua_State *luaenv = acl_lua_init();
	luaL_openlibs(luaenv);
	luaL_loadfile(luaenv, LUA_SCRIPT);

	char *url;
	while(1) {
		if(retbuf != NULL) {
			free(retbuf);
			retbuf = NULL;
		}
		get_json_send(luaenv);
		url = build_url(reportlink, 0);
		curl_send(url, &json_send[0], NULL);
		if(lastctltime != NULL) {
			url = build_url(ctrllink, 4, auth_key, 
				"?_=1234567890&time=", lastctltime, "&tag=1");
		} else {
			url = build_url(ctrllink, 1, auth_key);
		}
		curl_send(url, NULL, ret_call);
		lua_pushstring(luaenv, retbuf);
		lua_setglobal(luaenv, "CTRL_CMD");
		lua_getglobal(luaenv, "exec_str");
		lua_pop(luaenv, 1);
		lua_pcall(luaenv, 0, 0, 0);
	}
	lua_init();
}
